home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Technology Seed / Jan. '98 ATS.toast / NavServices1.0b3 / Navigation Services SDK / Examples / Sampler / Sampler ƒ / Mysprintf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-12  |  8.5 KB  |  439 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Mysprintf.c
  3.  
  4.     Copyright:    © 1997-1998 by Apple Computer, Inc., all rights reserved.
  5.  
  6. */
  7.  
  8. #pragma segment AppSeg
  9.  
  10. #ifndef __MEMORY__
  11. #include <Memory.h>
  12. #endif
  13.  
  14. #ifndef __STDARG__
  15. #include <stdarg.h>
  16. #endif
  17.  
  18. #ifndef __STDLIB__
  19. #include <StdLib.h>
  20. #endif
  21.  
  22. #ifndef __FP__
  23. #include <fp.h>
  24. #endif
  25.  
  26. #ifndef __MYSPRINTF__
  27. #include "Mysprintf.h"
  28. #endif
  29.  
  30. // local prototypes
  31. void Calc_Widths(UInt32* Lwidth, UInt32 Lplace, UInt32* Rwidth, UInt32 Rplace);
  32. void PrintString(StringPtr* s, StringPtr sval, Boolean LeftJustified, UInt32 Lwidth, UInt32 Rwidth);
  33. StringPtr numToBase(StringPtr destStr, UInt8 filler, UInt32 base, UInt32 digits,UInt32 value);
  34.  
  35. #define    MaxBase        16
  36. #define    MaxIndex     32
  37.  
  38. #undef    NULL
  39. #define    NULL        0L
  40.  
  41.  
  42. // ********************************************************************************
  43. // *    Myssprintf()                                                                        *
  44. // ********************************************************************************
  45. void Mysprintf(StringPtr s, StringPtr fmt,...)
  46. {
  47.     va_list        ap;    //    points to each unnamed arg in turn
  48.     UInt8        *p, *sval;
  49.     UInt32        ival;
  50.     double        dval;
  51.     float_t        fval;
  52.     UInt32        power;
  53.     Boolean        conversion;
  54.     Boolean        Lspace,ShowVal,LeftJustified;
  55.     UInt8        c,filler;
  56.     UInt32        Lwidth,Rwidth;
  57.     UInt32        Lplace,Rplace,width;
  58.     Str255        tStr;
  59.     StringPtr    aChar;
  60.     
  61.     va_start(ap,fmt);    //    make ap point to 1st unnamed arg
  62.     conversion = false;
  63.     for (p = fmt; *p; p++)
  64.         {
  65.         if (*p != '%' && !conversion)
  66.             {
  67.             *s++ = *p;
  68.             continue;
  69.             }
  70.         if (*p == '%' && !conversion)
  71.             {
  72.             conversion = true;
  73.             p++;    //    point to conversion char
  74.             Lwidth = NULL;
  75.             Lplace = NULL;
  76.             Rwidth = NULL;
  77.             Rplace = NULL;
  78.             Lspace = true;    //    calculate Lspace 1st
  79.             ShowVal = false;
  80.             LeftJustified = false;
  81.             filler    = ' ';    //    default to blank unless otherwise specified
  82.             }
  83.         c = *p;
  84.         switch(c)
  85.             {
  86.             case '%':    //    just a % char
  87.                     *s++ = '%';
  88.                     conversion = false;
  89.                 break;
  90.             case 'd':
  91.                     Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
  92.                     ival = va_arg(ap,int);
  93.                     numToBase(tStr,filler,10,Lwidth,ival);
  94.                     PrintString(&s, tStr, LeftJustified, Lwidth, Rwidth);
  95.                     conversion = false;
  96.                 break;
  97.             case 'f':
  98.                     Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
  99.                     fval = va_arg(ap, float_t);
  100.                     ival = (UInt32) fval;    //    during translation, the mantissa should be dropped
  101. //                    aChar = numToBase(tStr,filler,10,Lwidth,ival);
  102.                     aChar = numToBase(tStr,filler,10,0,ival);    //    experimenting w/ 0 width, so we get all digits
  103.                     *aChar++ = '.';    //    insert decimal point
  104.                         {
  105.                         UInt32 tindex = Rwidth;
  106.                         power = 1;
  107.                         while (tindex)
  108.                             {
  109.                             power *= 10;
  110.                             tindex--;
  111.                             }
  112.                         }
  113.                     dval = (fval-ival) * power;
  114.                     numToBase(aChar,filler,10,Rwidth,dval);
  115.                     PrintString(&s, tStr, LeftJustified, Lwidth, Rwidth);
  116.                     conversion = false;
  117.                     break;
  118.             case 's':
  119.                     Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
  120.                     sval = va_arg(ap, StringPtr);
  121.                     PrintString(&s, sval, LeftJustified, Lwidth, Rwidth);
  122.                     conversion = false;
  123.                 break;
  124.             case 'o':    //    octal
  125.                     Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
  126.                     if (ShowVal)
  127.                         {
  128.                         *s++ = '0';
  129.                         }
  130.                     ival = va_arg(ap,int);
  131.                     numToBase(tStr,filler,8,Lwidth,ival);
  132.                     PrintString(&s, tStr, LeftJustified, Lwidth, Rwidth);
  133.                     conversion = false;
  134.                     break;
  135.             case 'h':    //    h,     short
  136.             case 'l':    //    ell, long
  137.                 break;
  138.             case 'x':    //    hex lower
  139.             case 'X':    //    hex upper
  140.                     Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
  141.                     if (ShowVal)
  142.                         {
  143.                         if (c == 'x')
  144.                             BlockMove("0x",s,2);
  145.                         else
  146.                             BlockMove("0X",s,2);
  147.                             
  148.                         s+= 2;
  149.                         }
  150.                     ival = va_arg(ap,int);
  151.                     numToBase(tStr,filler,16,Lwidth,ival);
  152.                     PrintString(&s, tStr, LeftJustified, Lwidth, Rwidth);
  153.                     conversion = false;
  154.                 break;
  155.             case 'b':    //    binary
  156.                     Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
  157.                     if (ShowVal)
  158.                         {
  159.                         BlockMove("0b",s,2);
  160.                         s+= 2;
  161.                         }
  162.                     ival = va_arg(ap,int);
  163.                     numToBase(tStr,filler,2,Lwidth,ival);
  164.                     PrintString(&s, tStr, LeftJustified, Lwidth, Rwidth);
  165.                     conversion = false;
  166.                 break;
  167.             case '0':
  168.                     if (Lplace == NULL)
  169.                         filler = '0';
  170.             case '1':
  171.             case '2':
  172.             case '3':
  173.             case '4':
  174.             case '5':
  175.             case '6':
  176.             case '7':
  177.             case '8':
  178.             case '9':
  179.                 if (Lspace)
  180.                     {
  181.                     Lwidth = Lwidth << 8;
  182.                     Lplace++;
  183.                     Lwidth += c - '0';
  184.                     }
  185.                 else
  186.                     {
  187.                     Rwidth = Rwidth << 8;
  188.                     Rplace++;
  189.                     Rwidth += c - '0';
  190.                     }
  191.                 break;
  192.             case '.':
  193.                     Lspace = false;
  194.                     break;
  195.             case '#':
  196.                     ShowVal = true;
  197.                     break;
  198.             case '-':
  199.                     LeftJustified = true;
  200.                     break;
  201.             case '+':
  202.                 break;
  203.             case ' ':
  204.                 if (Lspace)
  205.                     {
  206.                     filler = ' ';
  207.                     }
  208.                 break;
  209.             case '*':
  210.                 width = va_arg(ap,int);    //    get width
  211.                 if (Lspace)
  212.                     {
  213.                     Lwidth = width;
  214.                     Lplace = NULL;
  215.                     }
  216.                 else
  217.                     {
  218.                     Rwidth = width;
  219.                     Rplace = NULL;
  220.                     }
  221.                 break;
  222.             default:
  223.                 *s++ = *p;
  224.                 break;
  225.         }
  226.     }
  227.     va_end(ap);    //    clean up when done
  228.     *s = 0;
  229. }
  230.  
  231.  
  232. // ********************************************************************************
  233. // *    Calc_Widths()
  234. // ********************************************************************************
  235. void Calc_Widths(UInt32* Lwidth,UInt32 Lplace, UInt32* Rwidth, UInt32 Rplace)
  236. {
  237.     UInt32 x,value,base;
  238.     Ptr    width;
  239.     
  240.     if (Lplace)
  241.         {
  242.         width = (Ptr) Lwidth+3;
  243.         for(x=0,value=0,base=1;x<Lplace;x++)
  244.             {
  245.             value += (*width) * base;
  246.             base *= 10;
  247.             width--;
  248.             }
  249.         *Lwidth = value;
  250.         }
  251.  
  252.     if (Rplace)
  253.         {
  254.         width = (Ptr) Rwidth+3;
  255.         for(x=0,value=0,base=1;x<Rplace;x++)
  256.             {
  257.             value += (*width) * base;
  258.             base *= 10;
  259.             width--;
  260.             }
  261.         *Rwidth = value;
  262.         }    
  263. }
  264.  
  265.  
  266. // ********************************************************************************
  267. // *    Calc_Widths()
  268. // *
  269. // *    PrintString
  270. // *
  271. // *    if (LeftJustified)
  272. // *        "|xxxxx      |"
  273. // *    else
  274. // *        "|      xxxxx|"
  275. // *
  276. // *    Lwidth = min # of chars
  277. // *    Rwidth = max # of chars
  278. // ********************************************************************************
  279. void PrintString(StringPtr* str, StringPtr sval, Boolean LeftJustified, UInt32 Lwidth, UInt32 Rwidth)
  280. {
  281.     StringPtr    s = *str;
  282.     UInt32        valid;
  283.     UInt32        validR = NULL;
  284.     
  285.     valid = Lwidth;
  286.     if (!valid)
  287.         valid = 255;    //    if NULL, default to max
  288.     
  289.     if (LeftJustified)
  290.     {    //
  291.         //    output data 1st, then fill
  292.         //
  293.         if (Rwidth)
  294.         {
  295.             validR = Rwidth;
  296.         }
  297.         else
  298.         {
  299.             validR = valid;
  300.         }
  301.         
  302.         while (validR && *sval)
  303.         {
  304.             *s++ = *sval;
  305.             validR--;
  306.             valid--;
  307.             sval++;
  308.         }
  309.  
  310.         while (valid)
  311.         {    //
  312.             //    we need to fill in the rest
  313.             //
  314.             *s++ = ' ';
  315.             valid--;
  316.         }
  317.     }
  318.     else
  319.     {    //
  320.         //    output filler 1st
  321.         //
  322.         if (Rwidth)
  323.         {
  324.             validR = valid - Rwidth;
  325.         }
  326.         else
  327.         {
  328.             valid = 255;    //    max allowed
  329.         }
  330.         
  331.         while (validR)
  332.         {    //
  333.             //    we need to fill in the rest
  334.             //
  335.             *s++ = ' ';
  336.             validR--;
  337.             valid--;
  338.         }
  339.  
  340.         //
  341.         //    output data 2nd
  342.         //
  343.         while (*sval && valid)
  344.         {
  345.             *s++ = *sval;
  346.             valid--;
  347.             sval++;
  348.         }
  349.     }
  350.     
  351.     *str = s;
  352. }
  353.  
  354.  
  355. // ********************************************************************************
  356. // *    StringPtr    numToBase     (Ptr destStr, char filler, int base, int digits, unsigned int value)
  357. // *    inputs:
  358. // *            destStr    :    destination string
  359. // *            filler    :    leading space filler, usually '0'
  360. // *            base    :    conversion base, 2=binary,8=octal,10=decimal,16=hex
  361. // *            digits    :    # of digits to display
  362. // *            value    :    number to convert
  363. // *    output:
  364. // *            the cstring representation of value will be moved to the location pointed to by "destStr"
  365. // *            return ptr to last char we store a null to
  366. // ********************************************************************************
  367. StringPtr numToBase(StringPtr destStr, UInt8 filler, UInt32 base, UInt32 digits, UInt32 value)
  368. {
  369.     UInt8    hex[16];
  370.     UInt8    tStr[MaxIndex+1];
  371.     UInt8*    aStr;
  372.     UInt32    index,lastIndex;
  373.     UInt8    digit,sign;
  374.  
  375.     // init hex array
  376.     for (index = 0, digit = '0'; index < 16; )
  377.         {
  378.         hex[index] = digit;
  379.         digit++;
  380.         index++;
  381.         if (index == 10)
  382.             digit = 'A';
  383.         }
  384.  
  385.     sign = 0;
  386.     if (base == 10)    //    special decimal handling
  387.         {
  388.         if (value &0x80000000)
  389.             {
  390.             value = abs(value);
  391.             sign = '-';    // automatically insert the '-' value
  392.             }
  393.         }
  394.     index = MaxIndex-1;
  395.     tStr[MaxIndex] = 0;    //    terminate string
  396.  
  397.     do     {
  398.         digit = (value % base) & 0x0F;    
  399.         tStr[index] = hex[digit];
  400.         value -= digit;
  401.         if (value)
  402.             {
  403.             value /= base;
  404.             }
  405.         index--;
  406.         }
  407.     while (value);
  408.     
  409.     if (sign)
  410.         {
  411.         tStr[index] = sign;
  412.         index--;
  413.         }
  414.     lastIndex = index+1;
  415.     
  416.     while(index!=-1)
  417.         {
  418.         tStr[index] = filler;
  419.         index--;
  420.         }
  421.     if (digits)
  422.         {
  423.         aStr = tStr + (MaxIndex-digits);
  424.         }
  425.     else
  426.         {
  427.         aStr = tStr+lastIndex;
  428.         }
  429.     
  430.     do    {
  431.         *destStr++ = *aStr++;    //    copy aStr to destStr
  432.         }
  433.     while (*aStr);
  434.     
  435.     *destStr = 0;                //    make sure we terminate the destination
  436.     
  437.     return (destStr);
  438. }
  439.